前幾天,我讓同一類固定探針進入不同位置:Day 10 是 HTML 屬性,Day 12 是行內 JavaScript 字串,Day 14 是網址片段進入 DOM,Day 16 是 POST 表單反射,Day 18 則先提交留言,再由另一個 GET 請求讀出。每次都安排 3 組對照;但「有反射」「已儲存」「瀏覽器讀到片段」與「探針真的執行」是不同事實。
Day 20,我沒有增加新的探針。我把前面 5 次本機實驗與其報告批次接成一份唯讀總覽,核對每組分類、原始回應與執行訊號,再從保存的表單 HTML 盤點輸入路徑。目標是讓我回頭看總表時,仍能找到當天的原始證據,而不是只剩下一個籠統的結論。
我從專案根目錄執行:
.venv/bin/python day-20/build_portfolio.py
程式讀取 Day 10、12、14、16、18 的 run-summary.json 與各組 JSON,確認每次都是 3 組、摘要分類與組別一致,並重新計算保存的原始回應 SHA-256。對 Day 16,我另外核對 POST 請求本文;對 Day 18,核對表單、提交、讀取各階段保存的檔案雜湊。它還要求 execution_observed 同時對應 alert(1) 與本次識別碼相符的 DOM 旗標。任一來源不一致,就停止產生總表。
報告部分,我只把來源摘要 SHA-256 與實驗相符的 API 批次接上,並逐組核對 validation.json 與 report.json 的通過狀態和工具分類。這次 5 個報告日的 3 組資料都顯示自動驗證通過;該欄只表示當天的格式、分類與引用規則通過,不代表我已用 Day 20 的程式重審每一句模型文字。Day 11、13、15、17、19 的作者核對紀錄仍須分開閱讀。
總表共核對 5 次實驗、15 組結果;每次的弱點對照都觀察到固定探針執行,其餘 10 組沒有觀察到本次探針執行,但原因各不相同:
| 實驗日 | 輸入與呈現位置 | 弱點對照 | 其他兩組的差異 |
|---|---|---|---|
| Day 10 | GET 輸入進入 HTML 屬性 | 探針執行 | 反射但未執行/未反射 |
| Day 12 | GET 輸入進入行內 JavaScript | 探針執行 | 留在字串資料/未反射 |
| Day 14 | URL fragment 進入 DOM | 探針執行 | 顯示為文字/頁面未使用片段 |
| Day 16 | POST 表單值進入回應 | 探針執行 | 顯示為文字/未反射 |
| Day 18 | POST 留言後,由 GET 讀取 | 探針執行 | 儲存但跳脫顯示/提交遭拒絕 |
Day 16 和 Day 18 都有 POST,但資料流不同。Day 16 的表單用 q 欄位送到 /post-vulnerable 等對照端點,結果就在同一次 POST 回應中。Day 18 的表單用 message 欄位送到 /vulnerable/submit 等端點,伺服器在本次實驗期間將資料放入記憶體,之後另一個 GET 請求從 /vulnerable/view 讀出。這個分開的讀取步驟,是判讀本次儲存型情境的關鍵。
我直接解析 6 份保存的表單原始 HTML,列出 method、action、具名欄位與提交按鈕的覆寫屬性,並把解析結果和當天記錄的表單資訊、原始 HTML 雜湊比對。
這一步只解析保存的靜態 HTML,沒有開啟頁面、執行 JavaScript 或自動提交表單。它能把已知的輸入路徑整理出來,不能宣稱找到了應用程式的所有表單。
我執行 7 個離線測試,分別檢查原始回應遭修改或缺檔、對話框與 DOM 旗標不相符、表單 HTML 或編碼類型被改動、儲存型實驗缺少提交來源,以及報告引用舊摘要或重複組別等情況。程式會拒絕不一致的來源,也不會把不相符的報告批次接到新實驗上。最後,我用當前保存檔重新產生 portfolio.json 與 portfolio.md,取得 5 次實驗、15 組結果及 6 份表單的總覽。
這是來源之間的一致性檢查,不是防止所有檔案同時遭修改的保證。總表也不能替各天的作者核對、更多輸入測試或正式網站評估背書。它能讓我在擴充檢查流程時,先知道每個結論依賴哪一份請求、回應、DOM 觀察與報告。
Day 20 的收穫是:把不同情境放在同一張表時,仍要保留「輸入從哪裡來、在哪一次請求中出現、瀏覽器做了什麼」這三條線。下一步若要自動探索更多入口,也應先沿著這些來源逐項核對。
那就…
明天見!